#
# Copyright (C) [2024] Xingyun Integrated Circuit, Inc.
#
# GreenCode was a private technology asset of Xingyun Integrated Circuit， Inc （Confidential）
# Author: Shawn.Tan
# Date: 2025.10.28
#
# History: Initial Version 2025.10.28
#
#
from gpgpu.EnvGPGPU import EnvGPGPU
from gpgpu.GenThreadGPGPU import GenThreadGPGPU
from base.Sequence import Sequence
from base.ChoicesModifier import ChoicesModifier
from DV.gpgpu.trees.instruction_tree import RV_G_instructions
from DV.gpgpu.trees.instruction_tree import RV32_G_instructions
from DV.gpgpu.trees.instruction_tree import ALU_Float_All_map
from DV.gpgpu.trees.instruction_tree import LDST_All_map
from DV.gpgpu.trees.instruction_tree import LDST32_All_map
from DV.gpgpu.trees.instruction_tree import RV32F_map


class MyMainSequence(Sequence):
    def generate(self, **kwargs):

        choices_mod = ChoicesModifier(self.genThread)

        for _ in range(10):

            # Generate instructions with the default choices settings
            # except for the paging choices for "Page size#4K
            # granule#S#stage 1" which was set before this generate was called
            # via the GenThreadInitialization below.

            self._gen_rv_g_instructions()

            # Modify the choices settings
            choices_mod.modifyOperandChoices(
                "Rounding mode",
                {"RNE": 0, "RTZ": 0, "RDN": 50, "RUP": 0, "RMM": 0, "DYN": 50},
            )

            choices_mod.modifyOperandChoices(
                "Read after write address reuse", {"No reuse": 50, "Reuse": 50}
            )
            choices_mod.commitSet()

            # generate instructions
            self._gen_data_processing_and_load_store_instructions()

            # undo the choices settings - revert back to prior
            choices_mod.revert()

    def _gen_rv_g_instructions(self):
        for _ in range(20):
            if self.getGlobalState("AppRegisterWidth") == 32:
                instr = self.pickWeighted(RV32_G_instructions)
            else:
                instr = self.pickWeighted(RV_G_instructions)

            self.genInstruction(instr)

    def _gen_data_processing_and_load_store_instructions(self):
        for _ in range(20):
            if self.getGlobalState("AppRegisterWidth") == 32:
                instr_mix = {RV32F_map: 10, LDST32_All_map: 10}
            else:
                instr_mix = {ALU_Float_All_map: 10, LDST_All_map: 10}

            instr = self.pickWeighted(instr_mix)
            self.genInstruction(instr)


# Modify the Paging Choices so that the test uses only 4K, 2M, or 4M page sizes
# This will be run before the MainSequence.generate()
def gen_thread_initialization(gen_thread):

    # when satp csr width is 32 bits then Sv32 is only paging mode possible...
    satp_info = gen_thread.getRegisterInfo("satp", gen_thread.getRegisterIndex("satp"))
    rv32 = satp_info["Width"] == 32

    choices_mod = ChoicesModifier(gen_thread)

    if rv32:
        # Sv32 only choices...
        choices_mod.modifyPagingChoices("Page size#4K granule#S#stage 1", {"4K": 10, "4M": 10})
    else:
        # Sv48 otherwise...
        choices_mod.modifyPagingChoices(
            "Page size#4K granule#S#stage 1",
            {"4K": 10, "2M": 10, "1G": 0, "512G": 0},
        )

    choices_mod.commitSet()


# Enable the GenThreadInitialization entry point
GenThreadInitialization = gen_thread_initialization

#  Points to the MainSequence defined in this file
MainSequenceClass = MyMainSequence

#  Using GenThreadGPGPU by default, can be overriden with extended classes
GenThreadClass = GenThreadGPGPU

#  Using EnvGPGPU by default, can be overriden with extended classes
EnvClass = EnvGPGPU
